//"This sample program is provided AS IS and may be used, executed, copied and modified without royalty payment by customer (a) for its own
//instruction and study, (b) in order to develop applications designed to run with an IBM WebSphere product, either for customer's own internal use
//or for redistribution by customer, as part of such an application, in customer's own products. "
//
//(C) COPYRIGHT International Business Machines Corp., 2005,2006
//All Rights Reserved * Licensed Materials - Property of IBM

package com;

import com.ibm.websphere.asynchbeans.WorkException;
import com.ibm.websphere.asynchbeans.WorkItem;
import com.ibm.websphere.asynchbeans.WorkManager;

/**
 * This takes a WorkManager which is wrapped in a proxy. The proxy calls
 * startWork using the J2EE context of the thread which created the ThreadFactory.
 * This ensures that when the thread is started, it gets dispatched using THAT
 * context and not the one of the thread calling start. This keeps things predictable
 * and it is much faster, since we don't have to apply a new context each time a 
 * Runnable is executed on this thread.
 * 
 * @author Billy Newport and Chris D Johnson
 */
public class ThreadWrapper extends Thread  
{
    // The WorkManager used to start this Thread
	private WorkManager wm;
    
    // The Runnable to submit start on the thread.
	private RunnableWrapper runnableWrapper;
    
    // Reference to a thread.
	private IThread t;
    
    // The resulting WorkItem of the submitted Runnable
	private WorkItem daemonItem;

	/**
	 * Every ThreadWrapper has a WorkManager and a RunnableWrapper associated with it.
	 */
	public ThreadWrapper(WorkManager wm, RunnableWrapper runnableWrapper) {
		super();
		this.wm = wm;
		this.runnableWrapper = runnableWrapper;
		this.t = (IThread)runnableWrapper;
	}

	/**
	 * @see java.lang.Thread#countStackFrames()
     * @deprecated
	 */
	public int countStackFrames() {
		return t.countStackFrames();
	}

	/* (non-Javadoc)
	 * @see java.lang.Thread#destroy()
	 */
	public void destroy() {
		 t.destroy();
	}

	/* (non-Javadoc)
	 * @see java.lang.Thread#getContextClassLoader()
	 */
	public ClassLoader getContextClassLoader() {
		return t.getContextClassLoader();
	}

	/* (non-Javadoc)
	 * @see java.lang.Thread#interrupt()
	 */
	public void interrupt() {
		t.interrupt();
	}

	/* (non-Javadoc)
	 * @see java.lang.Thread#isInterrupted()
	 */
	public boolean isInterrupted() {
		return t.isInterrupted();
	}

	/* (non-Javadoc)
	 * @see java.lang.Thread#setContextClassLoader(java.lang.ClassLoader)
	 */
	public void setContextClassLoader(ClassLoader cl) {
		t.setContextClassLoader(cl);
	}

	/**
	 * Start the thread.  This will start a WorkManager daemon thrad and will
	 * immediately submit the RunnableWrapper to it.
	 * @see java.lang.Thread#start()
	 */
	public synchronized void start() 
	{
		if(daemonItem != null)
		{
			throw new UnableToStartException("The thread has already been started");
		}
		try
		{
            // Start this thread as a Daemon Thread via the WorkManager
			daemonItem = wm.startWork(runnableWrapper, true);
		}
		catch(WorkException e)
		{
			throw new UnableToStartException(e);
		}
	}
	

}
